var Processor = require('./processor');
var Pipe =require('./pipe');
var DiffContext  =require( './contexts/diff');
var PatchContext  =require( './contexts/patch');
var ReverseContext  =require( './contexts/reverse');
var clone =require( './clone');

var trivial  =require( './filters/trivial');
var nested  =require( './filters/nested');
var arrays  =require( './filters/arrays');
var dates  =require( './filters/dates');
var texts  =require( './filters/texts');

class DiffPatcher {
  constructor(options) {
    this.processor = new Processor(options);
    this.processor.pipe(
      new Pipe('diff')
        .append(
          nested.collectChildrenDiffFilter,
          trivial.diffFilter,
          dates.diffFilter,
          texts.diffFilter,
          nested.objectsDiffFilter,
          arrays.diffFilter
        )
        .shouldHaveResult()
    );
    this.processor.pipe(
      new Pipe('patch')
        .append(
          nested.collectChildrenPatchFilter,
          arrays.collectChildrenPatchFilter,
          trivial.patchFilter,
          texts.patchFilter,
          nested.patchFilter,
          arrays.patchFilter
        )
        .shouldHaveResult()
    );
    this.processor.pipe(
      new Pipe('reverse')
        .append(
          nested.collectChildrenReverseFilter,
          arrays.collectChildrenReverseFilter,
          trivial.reverseFilter,
          texts.reverseFilter,
          nested.reverseFilter,
          arrays.reverseFilter
        )
        .shouldHaveResult()
    );
  }

  options(...args) {
    return this.processor.options(...args);
  }

  diff(left, right) {
    return this.processor.process(new DiffContext(left, right));
  }

  patch(left, delta) {
    return this.processor.process(new PatchContext(left, delta));
  }

  reverse(delta) {
    return this.processor.process(new ReverseContext(delta));
  }

  unpatch(right, delta) {
    return this.patch(right, this.reverse(delta));
  }

  clone(value) {
    return clone(value);
  }
}

module.exports = DiffPatcher;
